home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / shells / bashsrc.zoo / execute_cmd.c < prev    next >
C/C++ Source or Header  |  1991-06-05  |  44KB  |  1,684 lines

  1. /* execute_command.c -- Execute a COMMAND structure. */
  2.  
  3. /* Copyright (C) 1989 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7. Bash is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 1, or (at your option) any later
  10. version.
  11.  
  12. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with Bash; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <sys/types.h>
  23. #ifndef SONY
  24. #include <fcntl.h>
  25. #endif
  26. #include <sys/file.h>
  27. #include <sys/stat.h>
  28. #include <signal.h>
  29.  
  30. #ifndef SIGABRT
  31. #define SIGABRT SIGIOT
  32. #endif
  33.  
  34. #include <sys/param.h>
  35. #include <errno.h>
  36.  
  37. #include "shell.h"
  38. #include "y.tab.h"
  39. #include "builtins.h"
  40. #include "flags.h"
  41. #include "hash.h"
  42.  
  43. #ifdef JOB_CONTROL
  44. #include "jobs.h"
  45. #endif
  46.  
  47. #ifdef ALIAS
  48. #include "alias.h"
  49. #endif
  50.  
  51. extern int breaking, continuing, loop_level;
  52. extern int errno, sys_nerr;
  53. extern char *sys_errlist[];
  54.  
  55. #ifdef SYSV
  56. extern int last_made_pid;
  57. #endif
  58.  
  59. extern WORD_LIST *expand_words (), *expand_word ();
  60.  
  61. /* The value returned by the last synchronous command. */
  62. int last_command_exit_value = 0;
  63.  
  64. /* The list of redirections to preform which will undo the redirections
  65.    that I made in the shell. */
  66. REDIRECT *redirection_undo_list = (REDIRECT *)NULL;
  67.  
  68. /* Execute the command passed in COMMAND.  COMMAND is exactly what
  69.    read_command () places into GLOBAL_COMMAND.  See "shell.h" for the
  70.    details of the command structure.
  71.  
  72.    EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible
  73.    return values.  Executing a command with nothing in it returns
  74.    success. */
  75. execute_command (command)
  76.      COMMAND *command;
  77. {
  78.   /* Just do the command, but not asynchronously. */
  79.   return (execute_command_internal (command, 0, NO_PIPE, NO_PIPE));
  80. }
  81.  
  82. /* Returns 1 if TYPE is a shell control structure type. */
  83. int
  84. shell_control_structure (type)
  85.      enum command_type type;
  86. {
  87.   switch (type)
  88.     {
  89.     case cm_for:
  90.     case cm_case:
  91.     case cm_while:
  92.     case cm_until:
  93.     case cm_if:
  94.     case cm_group:
  95.       return (1);
  96.  
  97.     default:
  98.       return (0);
  99.     }
  100. }
  101.  
  102. execute_command_internal (command, asynchronous, pipe_in, pipe_out)
  103.      COMMAND *command;
  104.      int asynchronous;
  105.      int pipe_in, pipe_out;
  106. {
  107.   int exec_result;
  108.   REDIRECT *my_undo_list = (REDIRECT *)NULL;
  109.  
  110.   if (!command || breaking || continuing)
  111.     return (EXECUTION_SUCCESS);
  112.  
  113.   /* If a command was being explicitly run in a subshell, or if it is
  114.      a shell control-structure, and it has a pipe, then we do the command
  115.      in a subshell. */
  116.  
  117.   if (command->subshell ||
  118.       (shell_control_structure (command->type) &&
  119.        (pipe_out != NO_PIPE || pipe_in != NO_PIPE || asynchronous)))
  120.     {
  121.       int paren_pid;
  122.  
  123.       /* Fork a subshell, turn off the subshell bit, turn off job
  124.      control and call execute_command () on the command again. */
  125.       paren_pid = make_child (savestring (make_command_string (command)),
  126.                   asynchronous);
  127.       if (paren_pid == 0)
  128.     {
  129.       extern int interactive, login_shell;
  130.  
  131.       command->subshell = 0;
  132.  
  133.       /* Don't fork again, we are already in a subshell. */
  134.       asynchronous = 0;
  135.  
  136.       /* Subshells are neither login nor interactive. */
  137.       login_shell = interactive = 0;
  138.  
  139. #ifdef JOB_CONTROL
  140.       /* Delete all traces that there were any jobs running.  This is
  141.          only for subshells. */
  142.       without_job_control ();
  143. #endif
  144.       do_piping (pipe_in, pipe_out);
  145.       if (command->redirects)
  146.         if (!(do_redirections (command->redirects, 1, 0) == 0))
  147.           exit (EXECUTION_FAILURE);
  148.       exit (execute_command_internal
  149.          (command, asynchronous, NO_PIPE, NO_PIPE));
  150.     }
  151.       else
  152.     {
  153.       close_pipes (pipe_in, pipe_out);
  154.  
  155.       /* If we are part of a pipeline, and not the end of the pipeline,
  156.          then we should simply return and let the last command in the
  157.          pipe be waited for.  If we are not in a pipeline, or are the
  158.          last command in the pipeline, then we wait for the subshell
  159.          and return its exit status as usual. */
  160.       if (pipe_out != NO_PIPE)
  161.         return (EXECUTION_SUCCESS);
  162.       
  163.       stop_pipeline (asynchronous, (COMMAND *)NULL);
  164.  
  165.       if (!asynchronous)
  166.         return (last_command_exit_value = wait_for (paren_pid));
  167.       else
  168.         {
  169.           extern int interactive;
  170.           if (interactive)
  171.         describe_pid (paren_pid);
  172.           return (EXECUTION_SUCCESS);
  173.         }
  174.     }
  175.     }
  176.  
  177.   /* Handle WHILE FOR CASE etc. with redirections.  (Also '&' input
  178.      redirection.)  */
  179.   do_redirections (command->redirects, 1, 1);
  180.   my_undo_list = (REDIRECT *)copy_redirects (redirection_undo_list);
  181.  
  182.   switch (command->type)
  183.     {
  184.     case cm_for:
  185.       exec_result = execute_for_command (command->value.For);
  186.       break;
  187.  
  188.     case cm_case:
  189.       exec_result = execute_case_command (command->value.Case);
  190.       break;
  191.  
  192.     case cm_while:
  193.       exec_result = execute_while_command (command->value.While);
  194.       break;
  195.  
  196.     case cm_until:
  197.       exec_result = execute_until_command (command->value.While);
  198.       break;
  199.  
  200.     case cm_if:
  201.       exec_result = execute_if_command (command->value.If);
  202.       break;
  203.  
  204.     case cm_group:
  205.       if (asynchronous)
  206.     {
  207.       command->subshell = 1;
  208.       exec_result =
  209.         execute_command_internal (command, 1, pipe_in, pipe_out);
  210.     }
  211.       else
  212.     {
  213.       exec_result =
  214.         execute_command_internal (command->value.Group->command,
  215.                       asynchronous, pipe_in, pipe_out);
  216.     }
  217.       break;
  218.  
  219.     case cm_simple:
  220.       {
  221.     extern int last_asynchronous_pid, last_made_pid;
  222.     int last_pid = last_made_pid;
  223.     
  224. #ifdef JOB_CONTROL
  225.     extern int already_making_children;
  226. #endif 
  227.     exec_result =
  228.       execute_simple_command (command->value.Simple, pipe_in, pipe_out,
  229.                   asynchronous);
  230.  
  231.     /* If we forked to do the command, then we must
  232.        wait_for() the child. */
  233. #ifdef JOB_CONTROL
  234.     if (already_making_children && pipe_out == NO_PIPE)
  235. #else
  236.       if (pipe_out == NO_PIPE)
  237. #endif
  238.         {
  239.           if (last_pid != last_made_pid)
  240.         {
  241.           stop_pipeline (asynchronous, (COMMAND *)NULL);
  242.  
  243.           if (asynchronous)
  244.             {
  245.               extern int interactive;
  246.  
  247.               if (interactive)
  248.             describe_pid (last_made_pid);
  249.             }
  250.           else
  251.             exec_result = wait_for (last_made_pid);
  252.         }
  253.         }
  254.       }
  255.       break;
  256.  
  257.     case cm_connection:
  258.       switch (command->value.Connection->connector)
  259.     {
  260.       /* Do the first command asynchronously. */
  261.     case '&':
  262.       {
  263.         COMMAND *tc = command->value.Connection->first;
  264. #ifndef JOB_CONTROL
  265.         {
  266.           REDIRECT *tr = 
  267.         make_redirection (0, r_inputa_direction,
  268.                   make_word ("/dev/null"));
  269.           tr->next = tc->redirects;
  270.           tc->redirects = tr;
  271.         }
  272. #endif                /* !JOB_CONTROL */
  273.         exec_result = execute_command_internal (tc, 1, pipe_in, pipe_out);
  274.         if (command->value.Connection->second)
  275.           exec_result =
  276.         execute_command_internal (command->value.Connection->second,
  277.                       asynchronous, pipe_in, pipe_out);
  278.       }
  279.       break;
  280.  
  281.     case ';':
  282.       /* Just call execute command on both of them. */
  283.       execute_command (command->value.Connection->first);
  284.       exec_result =
  285.         execute_command_internal (command->value.Connection->second,
  286.                       asynchronous, pipe_in, pipe_out);
  287.       break;
  288.  
  289.     case '|':
  290.       {
  291.         /* Make a pipeline between the two commands. */
  292.         int fildes[2];
  293.         if (pipe (fildes) < 0)
  294.           {
  295.         report_error ("Pipe error %d", errno);
  296.         exec_result = EXECUTION_FAILURE;
  297.           }
  298.         else
  299.           {
  300.         execute_command_internal (command->value.Connection->first,
  301.                       asynchronous, pipe_in, fildes[1]);
  302.         exec_result =
  303.           execute_command_internal (command->value.Connection->second,
  304.                         asynchronous,